package cn.lcvc.xnc.authority.config.security;

import cn.lcvc.xnc.authority.config.security.filter.MyTokenFilter;
import cn.lcvc.xnc.authority.config.security.user.*;
import cn.lcvc.xnc.authority.service.impl.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

//@EnableWebSecurity //如果不希望启用spring security，这里也不应该加上
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserAuthenticationSuccessHandler userAuthenticationSuccessHandler;//自定义成功验证

    @Autowired
    private UserAuthenticationFailureHandler userAuthenticationFailureHandler;//自定义失败验证

    @Autowired
    private UserLogoutSuccessHandler logoutSuccessHandler;//自定义注销成功验证

    @Autowired
    private UserAuthenticationEntryPoint userAuthenticationEntryPoint;//自定义后台匿名用户访问无权限资源时的异常

    @Autowired
    private UserAccessDeniedHandler userAccessDeniedHandler;//自定义权限不足异常

    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    private MyTokenFilter myTokenFilter;
/*
    @Bean
    public FilterRegistrationBean MyTokenFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new MyTokenFilter());
        registration.addUrlPatterns("/abc");
        registration.setName("myTokenFilter");
        registration.setOrder(1);
        return registration;
    }*/

    //定义加密算法
    @Bean
    public MyPasswordEncoder myPasswordEncoder() {
        return new MyPasswordEncoder();
    }

    //配置spring security需要的用户Detail接口和要使用的加密算法
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(iSysUserService).passwordEncoder(myPasswordEncoder());
    }


    /**
     * Web层面的配置，一般用来配置无需权限校验的路径，也可以在HttpSecurity中配置，但是在web.ignoring()中配置效率更高。
     * web.ignoring()是一个忽略的过滤器，而HttpSecurity中定义了一个过滤器链，即使permitAll()放行还是会走所有的过滤器，
     * 直到最后一个过滤器FilterSecurityInterceptor认定是可以放行的，才能访问。
     */
    @Override
    public void configure(WebSecurity web){
        web.ignoring()
                .antMatchers("/upload/**")//不拦截上传文件展示的信息
                .antMatchers("/api/websocket/nooauth/**")//不拦截websockt的连接（不需要验证的）
                .antMatchers(MySecurityConfig.VERIFYCODEURL)//不拦截验证码
                 .antMatchers("/api/test/testHello")
                .antMatchers( "/api/shop/**")//不拦截前端请求
                .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagge‌​r-ui.html")//swagger文档不拦截
                .antMatchers( "/doc.html")//knife4j文档不拦截
        ;
    }


    ///HttpSecurity：一般用它来具体控制权限，角色，url等安全的东西。
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//SessionCreationPolicy.STATELESS表示不创建任何session；
                .and().csrf().disable()//禁用csrf,使用了Jwt不需要这个
                .cors()//允许跨域，注意必须配置相应的跨域过滤器
                .and().headers()
                .frameOptions().disable()//解决不允许存在iframe的问题
                .cacheControl();//启用缓存安全头
        http.authorizeRequests()
                //下面代码决定放行的路径，可以填写多个
                .antMatchers(MySecurityConfig.ADMINLOGINURL).permitAll()
                // 要拦截验证的请求
                .antMatchers("/api/backstage/**").authenticated()
                // 其余请求放行
                .anyRequest().permitAll()
//                .anyRequest().authenticated()
                .and()
                .formLogin().
                loginProcessingUrl(MySecurityConfig.ADMINLOGINURL) //设置登录处理地址，具体的账户和密码验证由spring security实现
                .successHandler(userAuthenticationSuccessHandler).failureHandler(userAuthenticationFailureHandler)
                .and()
                .exceptionHandling().authenticationEntryPoint(userAuthenticationEntryPoint) //无权限资源时的异常处理
                .and().logout()
                .logoutUrl(MySecurityConfig.ADMINLOGOUTURL).logoutSuccessHandler(logoutSuccessHandler)
                .and().addFilterBefore(myTokenFilter, UsernamePasswordAuthenticationFilter.class);


    }

}